#include "util_system.h"
#include <arpa/inet.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <fcntl.h>
#include <filesystem>
#include <format>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <limits>
#include <linux/if_vlan.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netpacket/packet.h>
#include <ranges>
#include <regex>
#include <signal.h>
#include <sstream>
#include <stdexcept>
#include <string>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <thread>
#include <unistd.h>
#include <unordered_set>
#include <vector>
namespace util::system
{
std::string ExecuteCommand(const std::string& command)
{
    std::string result;
    std::string real_cmd = command + " 2>&1";

    char  buffer[512] = {0};
    FILE* pipe        = popen(real_cmd.c_str(), "r");
    if (!pipe) return "ERROR";
    while (fgets(buffer, sizeof(buffer), pipe) != nullptr)
        result += buffer;
    pclose(pipe);
    return result;
}
int ExecuteCommand(const std::string& cmd, std::string& startRes)
{
    std::string fullCmd = cmd + " 2>&1";
    FILE*       fp      = popen(fullCmd.c_str(), "r");
    if (fp == nullptr)
    {
        startRes = "Failed to execute command.";
        return -1;
    }

    char buffer[256] = {0};
    startRes.clear();
    while (fgets(buffer, sizeof(buffer), fp) != nullptr)
        startRes += buffer;

    int resCode = pclose(fp);
    return resCode == 0 ? 0 : -1;
}

int ExecuteCommandWithTimeout(const std::string& command, int timeout,
                              std::string& result)
{
    pid_t pid = fork();
    if (pid == -1)
    {
        result = "Failed to fork process.";
        return -1;
    }
    else if (pid == 0)
    {
        // 子进程
        // 将命令字符串转换为参数数组
        std::vector<char*>       args;
        std::istringstream       iss(command);
        std::vector<std::string> tokens;
        std::string              token;
        while (iss >> token)
        {
            tokens.push_back(token);
        }
        if (!tokens.empty())
        {
            for (auto& token : tokens)
            {
                args.push_back(const_cast<char*>(token.c_str()));
            }

            // 执行命令
            for (auto& ptr : args)
            {
                std::cout << "args: " << ptr << std::endl;
            }
            int ret = execvp(args[0], args.data());
            std::cout << "ret: " << ret << std::endl;
        }

        // 如果 execvp 返回或者根本没执行，说明失败
        _exit(EXIT_FAILURE);
    }
    else
    {
        // 父进程
        int   status;
        pid_t wpid;
        int   timer = 0;

        // 等待子进程完成或超时
        while ((wpid = waitpid(pid, &status, WNOHANG)) == 0 && timer < timeout)
        {
            sleep(1);
            timer++;
        }

        if (wpid == -1)
        {
            result = "Failed to wait for child process.";
            return -1;
        }
        else if (wpid == 0)
        {
            // 超时，终止子进程
            kill(pid, SIGKILL);
            waitpid(pid, &status, 0);  // 确保子进程被回收
            result = "Command timed out.";
            return -1;
        }
        else
        {
            // 子进程正常退出
            if (WIFEXITED(status))
            {
                int exitStatus = WEXITSTATUS(status);
                if (exitStatus == 0)
                {
                    result = "Command executed successfully.";
                    return 0;
                }
                else
                {
                    result =
                        "Command failed with exit status: " + std::to_string(exitStatus);
                    return -1;
                }
            }
            else if (WIFSIGNALED(status))
            {
                int signal = WTERMSIG(status);
                result     = "Command terminated by signal: " + std::to_string(signal);
                return -1;
            }
        }
    }

    return -1;
}

// 存储大小为 Byte(字节)
size_t GetDiskTotalSpace(const std::string& path)
{
    struct statvfs buf;
    size_t         total_size = 0;

    if (statvfs(path.c_str(), &buf) == 0)
    {
        total_size = buf.f_blocks * buf.f_frsize;
    }

    return total_size;
}
// 存储大小为 Byte(字节)
size_t GetDiskUsableSpace(const std::string& path)
{
    struct statvfs buf;
    size_t         usable_size = 0;

    if (statvfs(path.c_str(), &buf) == 0)
    {
        usable_size = (buf.f_blocks - buf.f_bfree) * buf.f_frsize;
    }

    return usable_size;
}

/// 获取本次调用到上次调用这段时间内的CPU使用率。
/// CPU只能统计某段时间内的使用率,无法得到瞬时CPU使用率。
/// 外部通过timer固定时间间隔取CPU使用率。

float GetCpuUseRate()
{
    static unsigned long long total = 0;
    static unsigned long long used  = 0;
    float                     res   = 0.0f;
    std::ifstream             file("/proc/stat");
    if (!file.is_open()) return res;

    std::string text;
    std::getline(file, text);
    file.close();

    std::regex  pattern(R"(^\S*\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+))");
    std::smatch match;
    if (std::regex_search(text, match, pattern) && match.size() > 7)
    {
        unsigned long long user    = std::stoull(match[1].str());
        unsigned long long nice    = std::stoull(match[2].str());
        unsigned long long system  = std::stoull(match[3].str());
        unsigned long long idle    = std::stoull(match[4].str());
        unsigned long long iowait  = std::stoull(match[5].str());
        unsigned long long irq     = std::stoull(match[6].str());
        unsigned long long softirq = std::stoull(match[7].str());

        unsigned long long u = user + nice + system + softirq + irq;
        unsigned long long t = u + idle;
        res                  = static_cast<float>((u - used) * 100) / (t - total);
        total                = t;
        used                 = u;
    }
    return res;
}

float GetMemoryUseRate()
{
    float       res = 0.0f;
    std::string resMsg;
    auto        code = ExecuteCommand("free -b | grep Mem | awk '{print $2,$7}'", resMsg);
    if (code != 0)
        return res;

    std::istringstream       iss(resMsg);
    std::vector<std::string> col;
    std::string              token;

    while (std::getline(iss, token, ' '))
    {
        if (!token.empty())
            col.push_back(token);
    }

    if (col.size() < 2) return res;

    unsigned long long total, aval;
    try
    {
        total = std::stoull(col[0]);
        aval  = std::stoull(col[1]);
    }
    catch (...)
    {
        return res;
    }

    res = static_cast<float>(total - aval) / total * 100;
    return res;
}

float GetDiskUseRate()
{
    float                     res        = 0.0f;
    unsigned long long        totalSpace = 0;
    unsigned long long        usedSpace  = 0;
    std::unordered_set<dev_t> processedDevices;

    std::ifstream mounts("/proc/mounts");
    std::string   line;
    while (std::getline(mounts, line))
    {
        size_t spacePos1 = line.find(' ');
        size_t spacePos2 = line.find(' ', spacePos1 + 1);
        size_t spacePos3 = line.find(' ', spacePos2 + 1);

        std::string mountPoint = line.substr(spacePos1 + 1, spacePos2 - spacePos1 - 1);
        std::string fsType     = line.substr(spacePos2 + 1, spacePos3 - spacePos2 - 1);

        if (fsType == "proc" || fsType == "sysfs" || fsType == "tmpfs" || fsType == "devtmpfs" || fsType == "securityfs")
        {
            continue;
        }

        struct stat statBuf;
        if (stat(mountPoint.c_str(), &statBuf) != 0) continue;
        dev_t deviceID = statBuf.st_dev;
        if (processedDevices.find(deviceID) != processedDevices.end()) continue;

        processedDevices.insert(deviceID);

        struct statvfs stat;
        if (statvfs(mountPoint.c_str(), &stat) != 0) continue;

        unsigned long long blockSize   = stat.f_frsize;
        unsigned long long totalBlocks = stat.f_blocks;
        unsigned long long freeBlocks  = stat.f_bfree;

        unsigned long long usedBlocks = totalBlocks - freeBlocks;

        totalSpace += totalBlocks * blockSize;
        usedSpace += usedBlocks * blockSize;
    }

    if (totalSpace > 0)
    {
        res = static_cast<float>(usedSpace) * 100 / static_cast<float>(totalSpace);
    }

    return res;
}

std::vector<std::string> GetInterfaceName()
{
    std::vector<std::string> names;

    // 读取系统网口信息
    do {
        struct ifaddrs *ifaddr, *ifa;
        if (getifaddrs(&ifaddr) == -1)
        {
            break;
        }

        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
        {
            if (ifa->ifa_addr == NULL)
                continue;
            names.emplace_back(ifa->ifa_name);
        }

        freeifaddrs(ifaddr);
    } while (0);

    return names;
}

void GetInterfaceInfo(const std::string& name, std::string& ip, int& mask, bool& status)
{
    auto NetmaskToCIDR = [](const std::string& netmask)
    {
        struct in_addr addr;
        if (inet_aton(netmask.c_str(), &addr) == 0)
        {
            // 转换失败
            return -1;
        }
        // 转换为主机字节序
        uint32_t mask = ntohl(addr.s_addr);
        int      cidr = 0;
        // 计算掩码中前缀 1 的个数
        while (mask & 0x80000000)
        {
            cidr++;
            mask <<= 1;
        }
        return cidr;
    };

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) return;

    struct ifreq ifr;
    std::memset(&ifr, 0, sizeof(ifr));
    std::strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);

    // 获取接口的 IP 地址
    if (ioctl(sockfd, SIOCGIFADDR, &ifr) == 0)
    {
        struct sockaddr_in* ipaddr = (struct sockaddr_in*) &ifr.ifr_addr;
        ip                         = inet_ntoa(ipaddr->sin_addr);
    }

    // 获取接口的子网掩码
    if (ioctl(sockfd, SIOCGIFNETMASK, &ifr) == 0)
    {
        struct sockaddr_in* netmask    = (struct sockaddr_in*) &ifr.ifr_netmask;
        std::string         netmaskStr = inet_ntoa(netmask->sin_addr);
        mask                           = NetmaskToCIDR(netmaskStr);
    }

    // 获取接口状态（是否 UP）
    status = false;
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == 0)
        status = ifr.ifr_flags & IFF_UP;

    close(sockfd);
}

void GetInterfaceRate(const std::string& name, int& rx_rate, int& tx_rate)
{
    auto get_file_num = [](const std::string& path) -> size_t
    {
        std::ifstream file(path);
        unsigned long value = 0;
        if (file.is_open())
        {
            file >> value;
        }
        return value;
    };
    std::string rx_path = "/sys/class/net/" + name + "/statistics/rx_bytes";
    std::string tx_path = "/sys/class/net/" + name + "/statistics/tx_bytes";

    unsigned long prev_rx = get_file_num(rx_path);
    unsigned long prev_tx = get_file_num(tx_path);

    std::this_thread::sleep_for(std::chrono::seconds(1));

    unsigned long curr_rx = get_file_num(rx_path);
    unsigned long curr_tx = get_file_num(tx_path);

    rx_rate = curr_rx - prev_rx;
    tx_rate = curr_tx - prev_tx;
}

// 获取磁盘序列号
std::string GetDiskSerialNumber()
{
    std::string resMsg;
    auto        code = ExecuteCommand("lsblk -d --output NAME", resMsg);
    if (code != 0)
        return "";

    // 取最后一行
    std::string       disk_name = "";
    std::stringstream ss(resMsg);
    std::string       token;
    while (std::getline(ss, token, '\n'))
    {
        if (token.empty())
        {
            continue;
        }

        disk_name = token;
    }

    if (disk_name.empty())
    {
        return "";
    }

    code = ExecuteCommand(std::format("lsblk --nodeps -no serial /dev/{}", disk_name), resMsg);
    if (code != 0)
        return "";

    resMsg = resMsg.substr(0, resMsg.find_last_not_of('\n'));  // 去掉换行符
    return resMsg;
}

// 获取系统自启动以来的总时间
uint64_t GetSystemUpTime()
{
    std::filesystem::path uptime_file("/proc/uptime");
    std::ifstream         uptime_fs(uptime_file);
    if (!uptime_fs.is_open())
    {
        std::cerr << "Failed to open uptime file!" << std::endl;
        return 0;
    }

    double uptime = 0, free_seconds = 0;
    uptime_fs >> uptime >> free_seconds;
    uptime_fs.close();
    return static_cast<uint64_t>(uptime);
}
// 获取 MAC 地址
std::string GetMACAddress(struct ifaddrs* ifa)
{
    if (ifa->ifa_addr->sa_family == AF_PACKET)
    {
        auto*              s = (struct sockaddr_ll*) ifa->ifa_addr;
        std::ostringstream mac_stream;
        for (int i = 0; i < s->sll_halen; i++)
        {
            if (i > 0) mac_stream << ":";
            mac_stream << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(s->sll_addr[i]);
        }
        return mac_stream.str();
    }
    return "";
}

std::string GetOSVersion()
{
    // 读取 CentOS 的 /etc/redhat-release
    std::ifstream file("/etc/redhat-release");
    if (file)
    {
        std::string os_version;
        std::getline(file, os_version);
        file.close();
        return os_version;
    }

    // 如果 /etc/redhat-release 读取失败，使用 uname 获取通用 Linux 版本信息
    struct utsname buffer{};
    if (uname(&buffer) == 0)
    {
        return std::string(buffer.sysname) + " " + buffer.release;
    }

    return "Unknown Linux Version";
}

int GetMtu(const std::string& ifname)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1) return -1;

    struct ifreq ifr{};
    std::strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ);
    if (ioctl(fd, SIOCGIFMTU, &ifr) == -1)
    {
        close(fd);
        return -1;
    }

    close(fd);
    return ifr.ifr_mtu;
}

bool Exists(const std::string& name, const std::string& ip, const std::string& netmask)
{
    struct ifaddrs* ifaddr;
    if (getifaddrs(&ifaddr) == -1)
    {
        perror("getifaddrs");
        return false;
    }

    for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
    {
        if (ifa->ifa_addr == nullptr) continue;
        if (ifa->ifa_addr->sa_family != AF_INET) continue;  // 只处理 IPv4
        if (name != ifa->ifa_name) continue;
        if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) continue;  // 忽略 loopback

        if (ip.empty())
        {
            freeifaddrs(ifaddr);
            return true;  // 只判断网卡存在
        }

        // 获取地址
        char  addr_buf[INET_ADDRSTRLEN];
        void* addr_ptr = &((struct sockaddr_in*) ifa->ifa_addr)->sin_addr;
        inet_ntop(AF_INET, addr_ptr, addr_buf, INET_ADDRSTRLEN);
        std::string found_ip(addr_buf);

        // 获取掩码
        char  mask_buf[INET_ADDRSTRLEN];
        void* mask_ptr = &((struct sockaddr_in*) ifa->ifa_netmask)->sin_addr;
        inet_ntop(AF_INET, mask_ptr, mask_buf, INET_ADDRSTRLEN);
        std::string found_mask(mask_buf);

        if (found_ip == ip && found_mask == netmask)
        {
            freeifaddrs(ifaddr);
            return true;
        }
    }

    freeifaddrs(ifaddr);
    return false;
}

void SetValue(std::vector<std::string>& lines, const std::string& key, const std::string& value)
{
    for (auto& line : lines)
    {
        std::size_t pos = line.find('=');
        if (pos != std::string::npos)
        {
            std::string existingKey = line.substr(0, pos);
            if (existingKey == key)
            {
                line = key + "=" + value;
                return;
            }
        }
    }
    lines.push_back(key + "=" + value);
}

void SetFile(const std::string& name, const std::string& ip, const std::string& netmask, int vlan, int mtu, const std::string& osType)
{
    std::filesystem::path path;
    bool                  isUbuntuLegacy = (osType == "ubuntu-legacy");
    bool                  isUbuntuNew    = (osType == "ubuntu-new");
    bool                  isCentos       = (osType == "centos");

    if (isUbuntuLegacy)
    {
        path = std::filesystem::path(UbuntuNetcardPathLegacy) / (name + ".cfg");
    }
    else if (isUbuntuNew)
    {
        path = std::filesystem::path(UbuntuNetcardPathNew) / (name + ".yaml");
    }
    else if (isCentos)
    {
        path = std::filesystem::path(CentosNetcardPath) / ("ifcfg-" + name);
    }

    try
    {
        std::vector<std::string> lines;
        std::string              text;

        if (vlan == InvalidVlan)
        {
            if (!std::filesystem::exists(path)) return;
            std::ifstream      infile(path);
            std::ostringstream buffer;
            buffer << infile.rdbuf();
            text = buffer.str();
        }
        else
        {
            if (isUbuntuLegacy || isUbuntuNew)
            {
                path += "-vlan" + std::to_string(vlan);
            }
            else
            {
                path += "." + std::to_string(vlan);
            }

            if (!std::filesystem::exists(path))
            {
                if (isUbuntuLegacy)
                {
                    lines = {
                        "auto " + name + "." + std::to_string(vlan),
                        "iface " + name + "." + std::to_string(vlan) + " inet static",
                        "vlan-raw-device " + name};
                }
                else if (isUbuntuNew)
                {
                    lines = {
                        "network:",
                        "  version: 2",
                        "  ethernets:",
                        "    " + name + ":",
                        "      addresses: [" + ip + "/24]",
                        "      mtu: " + std::to_string(mtu)};
                }
                else if (isCentos)
                {
                    lines = {
                        "DEVICE=" + name + "." + std::to_string(vlan),
                        "VLAN=yes",
                        "USERCTL=no"};
                }
            }
            else
            {
                std::ifstream      infile(path);
                std::ostringstream buffer;
                buffer << infile.rdbuf();
                text = buffer.str();
            }
        }

        if (lines.empty())
        {
            std::istringstream stream(text);
            std::string        line;
            while (std::getline(stream, line))
            {
                if (!line.empty()) lines.push_back(line);
            }
        }

        if (isUbuntuLegacy)
        {
            SetValue(lines, "address", ip.empty() ? "" : ip);
            SetValue(lines, "netmask", netmask.empty() ? "" : netmask);
        }
        else if (isUbuntuNew)
        {
            // Netplan format follows YAML and is structured differently
        }
        else if (isCentos)
        {
            SetValue(lines, "BOOTPROTO", "static");
            SetValue(lines, "ONBOOT", "yes");
            SetValue(lines, "IPADDR", ip.empty() ? "" : ip);
            SetValue(lines, "NETMASK", netmask.empty() ? "" : netmask);
        }

        if (mtu != InvalidMtu && !isUbuntuNew) SetValue(lines, "mtu", std::to_string(mtu));

        std::ofstream outfile(path);
        for (const auto& line : lines)
        {
            outfile << line << "\n";
        }
    }
    catch (...)
    {
        throw std::runtime_error("设置网卡文件出错");
    }
}

std::vector<NetcardIp> GetEthInfo()
{
    std::map<std::string, NetcardIp> netcards;

    struct ifaddrs* ifaddr;
    if (getifaddrs(&ifaddr) == -1)
    {
        return {};
    }

    for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
    {
        if (!ifa->ifa_name || !ifa->ifa_addr) continue;

        std::string ifname(ifa->ifa_name);
        if (ifname.rfind("eth", 0) != 0) continue;  // only handle eth*

        std::string baseName = ifname;
        int         vlan     = -1;
        auto        dotPos   = ifname.find('.');
        if (dotPos != std::string::npos)
        {
            try
            {
                vlan     = std::stoi(ifname.substr(dotPos + 1));
                baseName = ifname.substr(0, dotPos);
            }
            catch (...)
            {
                continue;
            }
        }

        auto& nic = netcards[baseName];
        if (nic.name.empty())
        {
            nic.name = baseName;
            nic.mac  = GetMACAddress(ifa);
            nic.mtu  = GetMtu(baseName);
        }

        // 获取主网卡 IPv4 地址
        if (ifa->ifa_addr->sa_family == AF_INET)
        {
            char  ip[INET_ADDRSTRLEN], netmask[INET_ADDRSTRLEN];
            void* addr = &((struct sockaddr_in*) ifa->ifa_addr)->sin_addr;
            void* mask = &((struct sockaddr_in*) ifa->ifa_netmask)->sin_addr;
            inet_ntop(AF_INET, addr, ip, sizeof(ip));
            inet_ntop(AF_INET, mask, netmask, sizeof(netmask));

            if (vlan == -1)
            {
                nic.status  = (ifa->ifa_flags & IFF_RUNNING);
                nic.ip      = ip;
                nic.netmask = netmask;
            }
            else
            {
                NetcardVlan vlanInfo;
                vlanInfo.vlanId  = vlan;
                vlanInfo.ip      = ip;
                vlanInfo.netmask = netmask;
                nic.vlan.push_back(std::move(vlanInfo));
            }
        }
    }

    freeifaddrs(ifaddr);

    // 排序
    std::vector<NetcardIp> result;
    for (auto& [_, val] : netcards)
    {
        result.push_back(std::move(val));
    }

    std::sort(result.begin(), result.end(), [](const NetcardIp& a, const NetcardIp& b)
              {
        try {
            return std::stoi(a.name.substr(3)) < std::stoi(b.name.substr(3));
        } catch (...) {
            return false;
        } });

    return result;
}
int AddVlan(const std::string& name, int vlan)
{
    // 构造 VLAN 设备名称，例如 eth1.100
    std::string vlan_name = name + "." + std::to_string(vlan);

    // 打开 socket
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        throw std::runtime_error("无法创建 socket");
    }

    struct ifreq           ifr;
    struct vlan_ioctl_args vlan_args;

    // 清空结构体
    memset(&ifr, 0, sizeof(ifr));
    memset(&vlan_args, 0, sizeof(vlan_args));

    // 设置主网卡名称
    strncpy(vlan_args.device1, name.c_str(), IFNAMSIZ);
    vlan_args.u.VID = vlan;
    vlan_args.cmd   = ADD_VLAN_CMD;

    // 调用 ioctl 添加 VLAN
    if (ioctl(sock, SIOCSIFVLAN, &vlan_args) < 0)
    {
        close(sock);
        return 1;
    }
    close(sock);
    return 0;
}

int SetIpAddress(const std::string& iface, const std::string& ip, const std::string& netmask)
{
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
        throw std::runtime_error("无法创建 socket");
    struct ifreq       ifr{};
    struct sockaddr_in sa{};

    // 设置 IP 地址
    strncpy(ifr.ifr_name, iface.c_str(), IFNAMSIZ);
    sa.sin_family = AF_INET;
    inet_pton(AF_INET, ip.c_str(), &sa.sin_addr);
    memcpy(&ifr.ifr_addr, &sa, sizeof(struct sockaddr));
    if (ioctl(sock, SIOCSIFADDR, &ifr) < 0)
    {
        close(sock);
        return 1;
        throw std::runtime_error("设置 IP 地址失败");
    }

    // 设置子网掩码
    inet_pton(AF_INET, netmask.c_str(), &sa.sin_addr);
    memcpy(&ifr.ifr_netmask, &sa, sizeof(struct sockaddr));
    if (ioctl(sock, SIOCSIFNETMASK, &ifr) < 0)
    {
        close(sock);
        return 2;
        throw std::runtime_error("设置子网掩码失败");
    }

    // 启用接口
    if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0)
    {
        close(sock);
        return 3;
        throw std::runtime_error("获取接口标志失败");
    }
    ifr.ifr_flags |= IFF_UP;
    if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0)
    {
        close(sock);
        return 4;
        throw std::runtime_error("启动接口失败");
    }

    close(sock);
    return 0;
}

int DelVlan(const std::string& vlan_iface)
{
    // --- 删除 VLAN 接口 ---
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
        throw std::runtime_error("无法创建 socket");

    struct vlan_ioctl_args vlan_args;
    memset(&vlan_args, 0, sizeof(vlan_args));

    strncpy(vlan_args.device1, vlan_iface.c_str(), IFNAMSIZ);
    vlan_args.cmd = DEL_VLAN_CMD;

    if (ioctl(sock, SIOCSIFVLAN, &vlan_args) != 0)
    {
        close(sock);
        throw std::runtime_error("删除 VLAN 失败: " + vlan_iface);
    }

    close(sock);
    return 0;
}

std::string FindField(const std::string& line, const std::string& key)
{
    std::regex  pattern(key + R"( (\S+))");
    std::smatch match;
    if (std::regex_search(line, match, pattern))
        return match[1];
    return "";
}

std::vector<RouteInfo> GetRoutes()
{
    std::vector<RouteInfo> routes;

    FILE* fp = popen("ip route", "r");
    if (!fp) throw std::runtime_error("无法执行 ip route");

    char buffer[256];
    while (fgets(buffer, sizeof(buffer), fp))
    {
        std::string        line(buffer);
        std::istringstream iss(line);
        std::string        dest_token;
        iss >> dest_token;

        std::string ip   = dest_token;
        std::string mask = "32";

        if (ip == "default")
        {
            ip   = "0.0.0.0";
            mask = "0";
        }
        else
        {
            auto slash_pos = dest_token.find('/');
            if (slash_pos != std::string::npos)
            {
                ip   = dest_token.substr(0, slash_pos);
                mask = dest_token.substr(slash_pos + 1);
            }
        }

        RouteInfo info;
        info.destination = ip;
        info.netmask     = std::stoi(mask);
        info.interface   = FindField(line, "dev");

        std::string gw = FindField(line, "via");
        info.gateway   = gw.empty() ? "0.0.0.0" : gw;

        routes.push_back(info);
    }

    pclose(fp);
    return routes;
}

int AddRouteViaNetlink(const RouteInfo& info)
{
    if (info.gateway.empty() && info.interface.empty())
        return 1;

    int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sock < 0)
        throw std::runtime_error("无法创建 netlink socket");

    // 构造 netlink 请求
    struct
    {
        struct nlmsghdr nlh;
        struct rtmsg    rtm;
        char            buffer[256];
    } req{};

    req.nlh.nlmsg_len   = NLMSG_LENGTH(sizeof(rtmsg));
    req.nlh.nlmsg_type  = RTM_NEWROUTE;
    req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
    req.nlh.nlmsg_seq   = 1;

    req.rtm.rtm_family   = AF_INET;
    req.rtm.rtm_table    = RT_TABLE_MAIN;
    req.rtm.rtm_protocol = RTPROT_BOOT;
    req.rtm.rtm_scope    = RT_SCOPE_UNIVERSE;
    req.rtm.rtm_type     = RTN_UNICAST;
    req.rtm.rtm_dst_len  = info.netmask;

    struct rtattr* rta     = (struct rtattr*) req.buffer;
    int            rta_len = 0;

    // 目标地址
    in_addr dst{};
    if (inet_pton(AF_INET, info.destination.c_str(), &dst) != 1)
        throw std::runtime_error("目标地址不合法");
    rta->rta_type = RTA_DST;
    rta->rta_len  = RTA_LENGTH(sizeof(dst));
    memcpy(RTA_DATA(rta), &dst, sizeof(dst));
    rta_len += RTA_ALIGN(rta->rta_len);
    rta = RTA_NEXT(rta, rta_len);

    // 网关地址（如果有）
    in_addr gw{};
    if (!info.gateway.empty())
    {
        if (inet_pton(AF_INET, info.gateway.c_str(), &gw) != 1)
            throw std::runtime_error("网关地址不合法");

        rta->rta_type = RTA_GATEWAY;
        rta->rta_len  = RTA_LENGTH(sizeof(gw));
        memcpy(RTA_DATA(rta), &gw, sizeof(gw));
        rta_len += RTA_ALIGN(rta->rta_len);
        rta = RTA_NEXT(rta, rta_len);
    }

    // 输出接口索引（如果有）
    if (!info.interface.empty())
    {
        int ifindex = if_nametoindex(info.interface.c_str());
        if (ifindex == 0)
            throw std::runtime_error("找不到接口: " + info.interface);

        rta->rta_type = RTA_OIF;
        rta->rta_len  = RTA_LENGTH(sizeof(ifindex));
        memcpy(RTA_DATA(rta), &ifindex, sizeof(ifindex));
        rta_len += RTA_ALIGN(rta->rta_len);
    }

    req.nlh.nlmsg_len += rta_len;

    // 发送消息
    struct sockaddr_nl nladdr{};
    nladdr.nl_family = AF_NETLINK;

    struct iovec  iov = {&req, req.nlh.nlmsg_len};
    struct msghdr msg{};
    msg.msg_name    = &nladdr;
    msg.msg_namelen = sizeof(nladdr);
    msg.msg_iov     = &iov;
    msg.msg_iovlen  = 1;

    if (sendmsg(sock, &msg, 0) < 0)
    {
        close(sock);
        return 2;
        throw std::runtime_error("添加路由失败（sendmsg）");
    }

    close(sock);
    // 永久写入
    // 获取系统信息
    struct utsname sysInfo;
    if (uname(&sysInfo) != 0)
        throw std::runtime_error("无法获取系统信息");

    std::string distro;
    std::ifstream osRelease("/etc/os-release");
    if (osRelease)
    {
        std::string line;
        while (std::getline(osRelease, line))
        {
            if (line.find("ID=") == 0)
            {
                distro = line.substr(3);
                break;
            }
        }
    }

    if (distro.find("ubuntu") != std::string::npos || distro.find("debian") != std::string::npos)
    {
        // Debian/Ubuntu 系列
        // todo: 新版本
        std::ofstream interfaces("/etc/network/interfaces", std::ios::app);
        if (!interfaces)
            throw std::runtime_error("无法写入 /etc/network/interfaces");

        interfaces << "\n# 添加永久路由\n";
        interfaces << "up ip route add " << info.destination << "/" << info.netmask
                   << " via " << info.gateway << " dev " << info.interface << "\n";
    }
    else if (distro.find("centos") != std::string::npos || distro.find("rhel") != std::string::npos)
    {
        // CentOS/RHEL 系列
        std::ostringstream routeFile;
        routeFile << "/etc/sysconfig/network-scripts/route-" << info.interface;

        std::ofstream routeConfig(routeFile.str(), std::ios::app);
        if (!routeConfig)
            throw std::runtime_error("无法写入 " + routeFile.str());

        routeConfig << info.destination << "/" << info.netmask
                    << " via " << info.gateway << " dev " << info.interface << "\n";
    }
    else
    {
        // 通用方案：写入 /etc/rc.local
        std::ofstream rcLocal("/etc/rc.local", std::ios::app);
        if (!rcLocal)
            throw std::runtime_error("无法写入 /etc/rc.local");

        rcLocal << "ip route add " << info.destination << "/" << info.netmask
                << " via " << info.gateway << " dev " << info.interface << "\n";
    }
    return 0;
}

int DeleteRouteViaNetlink(const RouteInfo& info)
{
    int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sock < 0)
        throw std::runtime_error("无法创建 netlink socket");

    struct {
        struct nlmsghdr nlh;
        struct rtmsg rtm;
        char buffer[256];
    } req{};

    req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
    req.nlh.nlmsg_type = RTM_DELROUTE;
    req.nlh.nlmsg_flags = NLM_F_REQUEST;
    req.nlh.nlmsg_seq = 1;

    req.rtm.rtm_family = AF_INET;
    req.rtm.rtm_table = RT_TABLE_MAIN;
    req.rtm.rtm_protocol = RTPROT_BOOT;
    req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
    req.rtm.rtm_type = RTN_UNICAST;
    req.rtm.rtm_dst_len = info.netmask;

    struct rtattr* rta = (struct rtattr*)req.buffer;
    int rta_len = 0;

    // 目标地址
    in_addr dst{};
    if (inet_pton(AF_INET, info.destination.c_str(), &dst) != 1)
        throw std::runtime_error("目标地址不合法");
    rta->rta_type = RTA_DST;
    rta->rta_len = RTA_LENGTH(sizeof(dst));
    memcpy(RTA_DATA(rta), &dst, sizeof(dst));
    rta_len += RTA_ALIGN(rta->rta_len);
    rta = RTA_NEXT(rta, rta_len);

    // 网关（如果有）
    if (!info.gateway.empty() && info.gateway != "0.0.0.0")
    {
        in_addr gw{};
        if (inet_pton(AF_INET, info.gateway.c_str(), &gw) != 1)
            throw std::runtime_error("网关地址不合法");
        rta->rta_type = RTA_GATEWAY;
        rta->rta_len = RTA_LENGTH(sizeof(gw));
        memcpy(RTA_DATA(rta), &gw, sizeof(gw));
        rta_len += RTA_ALIGN(rta->rta_len);
        rta = RTA_NEXT(rta, rta_len);
    }

    // 接口（如果有）
    if (!info.interface.empty())
    {
        int ifindex = if_nametoindex(info.interface.c_str());
        if (ifindex == 0)
            throw std::runtime_error("找不到接口: " + info.interface);
        rta->rta_type = RTA_OIF;
        rta->rta_len = RTA_LENGTH(sizeof(ifindex));
        memcpy(RTA_DATA(rta), &ifindex, sizeof(ifindex));
        rta_len += RTA_ALIGN(rta->rta_len);
    }

    req.nlh.nlmsg_len += rta_len;

    sockaddr_nl sa = {};
    sa.nl_family = AF_NETLINK;

    struct iovec iov = { &req, req.nlh.nlmsg_len };
    struct msghdr msg = {};
    msg.msg_name = &sa;
    msg.msg_namelen = sizeof(sa);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    if (sendmsg(sock, &msg, 0) < 0)
    {
        close(sock);
        return 1;
        throw std::runtime_error("删除路由失败（sendmsg）");
    }

    close(sock);
    //todo: 适配不同系统
    std::filesystem::path path = "/etc/sysconfig/static-routes";
    if (!std::filesystem::exists(path))
    {
        std::cerr<<"删除路由失败(文件不存在)"<<std::endl;
    }
    std::ifstream in(path);
    std::ostringstream out;
    std::string line;
    while (std::getline(in, line)) {
        if (line.find(info.destination) != std::string::npos &&
            line.find(std::to_string(info.netmask)) != std::string::npos &&
            line.find(info.interface) != std::string::npos) {
            continue;
            }
        out << line << "\n";
    }
    in.close();
    std::ofstream(path) << out.str();
    return 0;
}
}  // namespace util::system
